package com.itsu.spbspider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itsu.spbspider.entity.Crawler;
import com.itsu.spbspider.entity.Job;
import com.itsu.spbspider.entity.News;
import com.itsu.spbspider.exception.SystemException;
import com.itsu.spbspider.mapper.CrawlerMapper;
import com.itsu.spbspider.mapper.JobMapper;
import com.itsu.spbspider.mapper.NewsMapper;
import com.itsu.spbspider.service.JobService;
import com.itsu.spbspider.util.ProjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Slf4j
public class JobServiceImpl implements JobService {

    @Resource
    JobMapper jobMapper;

    @Resource
    NewsMapper newsMapper;

    @Resource
    CrawlerMapper crawlerMapper;

    @Override
    public Page getJobList(Integer page, Integer limit) throws SystemException {
        Page<Job> ipage = null;
        try {
            updateJob();
            ipage = new Page<>();
            ipage.setCurrent(page).setSize(limit);
            ipage = jobMapper.selectPage(ipage, new QueryWrapper<>());
        } catch (Exception e) {
            throw new SystemException(e);
        }
        return ipage;
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateJob() throws SystemException {
        try {
            List<Job> jobs = jobMapper.selectList(null);
            for (Job job : jobs) {
                String tableName = job.getDataObjName();
                if ((tableName + "Mapper").toUpperCase().equals("NEWSMAPPER")) {
                    QueryWrapper<News> condition = new QueryWrapper<>();
                    condition.eq("job_id", job.getId());
                    Integer count = newsMapper.selectCount(condition);
                    job.setDataCount(count.longValue());
                    Date lastErrorTime = job.getLastErrorTime();
                    if (lastErrorTime != null) {
                        String health = this.compare2Now(lastErrorTime);
                        job.setHeath(health);
                    }
                    jobMapper.updateById(job);

                }
            }
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }

    public String compare2Now(Date date) {
        long time = new Date().getTime() - date.getTime();
        long days = time / (1000 * 60 * 60 * 24);
        String content = null;
        if (days <= 7) {
            content = "近7日内发送过异常";
        } else if (days > 7 && days <= 30) {
            content = "近30天内发送过异常";
        } else {
            content = "已超过30天无异常发生";
        }
        return content;
    }

    @Override
    public Job getJobById(String id) throws SystemException {
        try {
            return jobMapper.selectById(id);
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateJob(Job job) throws SystemException {
        try {
            jobMapper.updateById(job);
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addNewJob(Map paramsMap) throws Exception {
        try {
            String jobName = (String) paramsMap.get("jobName");
            Integer timeInterval = Integer.valueOf(paramsMap.get("timeInterval").toString());
            String unit = (String) paramsMap.get("unit");
            Integer retry = Integer.valueOf(paramsMap.get("retry").toString());
            String url = (String) paramsMap.get("url");
            String method = (String) paramsMap.get("method");
            String params = (String) paramsMap.get("params");
            String headers = (String) paramsMap.get("headers");
            Crawler crawler = new Crawler();
            crawler.setHeaders(headers);
            crawler.setParams(params);
            crawler.setMethod(method);
            crawler.setUrl(url);
            crawlerMapper.insert(crawler);
            Integer crawlerId = crawler.getId();
            if (crawlerId == null || crawlerId.intValue() == 0) throw new Exception("get null of crawler id");

            Job job = new Job();
            job.setJobName(jobName);
            job.setTimeInterval(timeInterval);
            job.setRetry(retry);
            job.setUnit(unit);
            job.setId(UUID.randomUUID().toString());
            job.setTimeInterval(ProjectUtil.caculateSeconds(job));
            job.setCrawlerId(crawlerId);
            job.setStatus("N");
            job.setHeath("正常");
            job.setDataObjName("news");
            job.setSuccessPer("100%");
            jobMapper.insert(job);
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }

    @Override
    public List<String> getJobModels() throws Exception {
        try {
            QueryWrapper<Job> condition = new QueryWrapper<>();
            condition.select("job_name");
            List<Job> jobs = jobMapper.selectList(condition);
            return jobs.stream().map(x -> x.getJobName()).collect(Collectors.toList());
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delteJobById(String jobId) throws Exception {
        try {
            Job job = jobMapper.selectById(jobId);
            crawlerMapper.deleteById(job.getCrawlerId());
            jobMapper.deleteById(jobId);
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }
}
